package Store;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import com.sleepycat.collections.StoredEntrySet;
import com.sleepycat.collections.TransactionRunner;
import com.sleepycat.collections.TransactionWorker;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.TransactionConfig;
import com.sleepycat.je.rep.monitor.NewMasterEvent;

import Config.GlobalLog;
import EurekaAnalyzer.IDInformation;
import Statistics.IDGraph;
import Statistics.IDGraphNode;

/**
 * @author Xenophon
 * @version 2009-12-5
 *
 */
public class StoreManager {
	private HashMap<String, IDInformation> pool;
	private String 		idDataPath;
	private StoreDB 	idInfoDB;
	private StoreView 	idInfoview;
	
	private IDGraph     graph;
	private String  	graphDbPath;
	private StoreDB 	graphDb;
	private GraphDBView graphDbView;

	private boolean     isIDDBOpened 	= false;
	private boolean     isGraphDBOpened = false;
	
	public StoreManager(String dataPath,String graphDataPath)
	{
		SetUpIDInfoDB(dataPath);
		SetUpGraphDatabase(graphDataPath);
	}
	
	public void SetUpGraphDatabase(String graphDb)
	{
		this.graphDbPath = graphDb;
		this.graphDb = new StoreDB(graphDb);
		this.graphDbView = new GraphDBView(this.graphDb);
		isGraphDBOpened = true;
		
	}
	
	public StoreManager()
	{}
	
	@Deprecated
	public StoreManager(String path)
	{
		SetUpIDInfoDB(path);
	}
	
	public void SetUpIDInfoDB(String path)
	{
		GlobalLog.AddLog("Begin Setup IDinfo Database");
		this.idDataPath = path;
		this.idInfoDB = new StoreDB(path);
		this.idInfoview = new StoreView(idInfoDB);
		isIDDBOpened  	= true;
		GlobalLog.AddLog("End Setup IDinfo Database");
	}
	
	private void StoreIDInformation()
	{
		Iterator iter = pool.entrySet().iterator();
		Map target = idInfoview.GetIDInfoMap();
		System.out.println("Storing data into the  database...");
		while(iter.hasNext())
		{
			Map.Entry en = (Map.Entry)iter.next();
			target.put(new IDInfoKey((String) en.getKey()), en.getValue());
		}
		System.out.println("Done...");
	}
	
	private class StoreIDRunner implements TransactionWorker
	{
		public void doWork()
		{
			StoreIDInformation();
		}
	}
	
	public void Store(HashMap<String, IDInformation> data)
	{
		pool = data;
		TransactionRunner tr = new TransactionRunner(idInfoDB.GetEnvironment());
		try {
			tr.run(new StoreIDRunner());
		} catch (DatabaseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		ClearPool();
	}
	
	//////////////////////////////////////////////////////////////////
	private void StoreGraph()
	{
		Iterator iter = graph.GetNodeMap().entrySet().iterator();
		Map target = graphDbView.GetIDInfoMap();
		System.out.println("Storing graph into the  database...");
		while(iter.hasNext())
		{
			Map.Entry en = (Map.Entry)iter.next();
			target.put(new IDInfoKey((String) en.getKey()), en.getValue());
		}
		System.out.println("Done...");
	}
	
	private class StoreGraphRunner implements TransactionWorker
	{
		public void doWork()
		{
			StoreGraph();
		}
	}
	
	public void StoreGraph(IDGraph graph)
	{
		this.graph = graph;
		TransactionRunner tr = new TransactionRunner(graphDb.GetEnvironment());
		try {
			tr.run(new StoreGraphRunner());
		} catch (DatabaseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//////////////////////////////////////////////////////////////////
	public IDInformation GetIDInfoByID(String id)
	{
		Map target = idInfoview.GetIDInfoMap();
		return (IDInformation) target.get(new IDInfoKey(id));
	}
	
	
	public HashMap<String, IDGraphNode> GetIDGraphData()
	{
		HashMap<String, IDGraphNode> result = new HashMap<String, IDGraphNode>();
		StoredEntrySet<IDInfoKey, IDGraphNode> entrySet = (StoredEntrySet<IDInfoKey, IDGraphNode>)graphDbView.GetIDInfoMap().entrySet();
		Iterator itor = entrySet.iterator();
		while(itor.hasNext())
		{
			Map.Entry<IDInfoKey,IDGraphNode> entry = (Map.Entry<IDInfoKey, IDGraphNode>)itor.next(); 
			result.put(entry.getKey().GetID(),entry.getValue());
		}
		return result;
	}
	
	public void StoreIDInformation(String id, IDInformation info)
	{
		Map target = idInfoview.GetIDInfoMap();
		target.put(new IDInfoKey(id), info);
	}
	
    /**
     * Close the database cleanly.
     */
    public void Close()
        throws DatabaseException {
		if (isIDDBOpened)
		{
			idInfoDB.Close();
			System.out.println("ID-Info database closed...");
		}
		if (isGraphDBOpened)
		{
			graphDb.Close();
			System.out.println("Graph Database closed...");
		}
		isGraphDBOpened = false;
		isIDDBOpened  	= false;
    }
    
	public void ClearPool()
	{
		Set<Entry<String, IDInformation>> entrySet = pool.entrySet();
		for (Entry entry: entrySet) {
			((IDInformation) entry.getValue()).Clear();
		}
		pool.clear();
	}
	
	public IDGraph CreateIDGraphFromIDInfoDB()
	{
		return new IDGraph(idInfoview.GetIDInfoMap()); 
	}

}
